package cn.dface.app.deploy.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Properties;

import org.springframework.stereotype.Service;

import cn.dface.app.deploy.entity.Application;
import cn.dface.app.deploy.entity.StatusType;
import cn.dface.app.deploy.exception.DeployException;

@Service("ApplicationService")
public class ApplicationService {
	
	private final static Class<Application> APPLICATION_CLAZZ = Application.class;
	
	public Application getApplication(File appConfigFile) {
		try (InputStream input = new FileInputStream(appConfigFile)) {
			Properties prop = new Properties();
			prop.load(input);
			Object appObj = APPLICATION_CLAZZ.newInstance();
			for (Field field : APPLICATION_CLAZZ.getDeclaredFields()) {
				String fieldName = field.getName();
				String setMethodName = "set" + (char) (fieldName.charAt(0) - 32) + fieldName.substring(1);
				Method method = APPLICATION_CLAZZ.getMethod(setMethodName, field.getType());
				if (field.getType().isEnum()) {
					method.invoke(appObj, StatusType.fromValue(prop.getProperty(fieldName)));
				} else if (field.getType() == Calendar.class) {
					Calendar calendar = Calendar.getInstance();
					calendar.setTimeInMillis(Long.valueOf(prop.getProperty(fieldName)));
					method.invoke(appObj, calendar);
				} else {
					method.invoke(appObj, prop.getProperty(fieldName));
				}
			}
			return (Application) appObj;
		} catch (Exception e) {
			return null;
		}
	}
	
	public void saveApplication(Application app, File appConfigFile) throws DeployException {
		try (OutputStream output = new FileOutputStream(appConfigFile)) {
			Properties prop = new Properties();
			for (Field field : APPLICATION_CLAZZ.getDeclaredFields()) {
				String fieldName = field.getName();
				String getMethodName = "get" + (char) (fieldName.charAt(0) - 32) + fieldName.substring(1);
				Method method = APPLICATION_CLAZZ.getMethod(getMethodName);
				if (field.getType() == Calendar.class) {
					prop.setProperty(field.getName(), String.valueOf(((Calendar)method.invoke(app)).getTimeInMillis()));
				} else {
					prop.setProperty(field.getName(), method.invoke(app).toString());
				}
			}
			prop.store(output, null);
		} catch (IOException | NoSuchMethodException | SecurityException | 
					IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
			throw new DeployException(e.getMessage());
		}
	}
	
	public void deleteApplication(File appConfigFile) throws DeployException {
		if (appConfigFile.exists()) {
			appConfigFile.delete();
		} else {
			String appName = appConfigFile.getName().substring(0, appConfigFile.getName().lastIndexOf(".") + 1);
			throw new DeployException("App named " + appName + "not found");
		}
	}
	
}
